using System;
using System.Drawing;
using System.Windows.Forms;

class Program {
    static void Main(){
        // Application.Run(new KeyForm());
        Application.Run(new KeyExample());
    }
}

class KeyForm : Form {

    public  KeyForm(){
        Text = "Key Form";
        BackColor = SystemColors.Window;
        ForeColor = SystemColors.WindowText;
    }

    protected override void OnKeyDown(KeyEventArgs e)
    {
        exitOnX(e);
    }

    void exitOnX(KeyEventArgs kea){
        if(kea.KeyCode == Keys.X){
            Close();
        }
    }
}


class KeyExample : Form {
    
    enum EventType{
        None,
        KeyDown,
        KeyUp,
        KeyPress
    }
    struct KeyEvent{
        public EventType evtType;
        public EventArgs evtargs;
    }

    const int iNumLines = 25;
    int iNumValid = 0;
    int iInserIndex = 0;
    KeyEvent[] akeyevt = new KeyEvent[iNumLines];
    int xEvent,xChar,xCode,xMods,xData,xShift,xCtrl,xAlt,xRight;

    public KeyExample(){
        Text = "KeyExample";
        BackColor = SystemColors.Window;
        ForeColor = SystemColors.WindowText;
        
        xEvent = 0;
        xChar = xEvent+5*Font.Height;
        xCode = xChar+5*Font.Height;
        xMods = xCode+8*Font.Height;
        xData = xMods+8*Font.Height;
        xShift = xData+8*Font.Height;
        xCtrl = xShift+5*Font.Height;
        xAlt = xCtrl+5*Font.Height;
        xRight = xAlt+5*Font.Height;

        ClientSize = new Size(xRight,Font.Height*(iNumLines + 1));
        FormBorderStyle = FormBorderStyle.Fixed3D;
        MaximizeBox = false;
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        var g = e.Graphics;

        BoldUnderline(g,"Event",xEvent,0);
        BoldUnderline(g,"KeyChar",xChar,0);
        BoldUnderline(g,"KeyCode",xCode,0);
        BoldUnderline(g,"Modifiers",xMods,0);
        BoldUnderline(g,"KeyData",xData,0);
        BoldUnderline(g,"Shift",xShift,0);
        BoldUnderline(g,"Control",xCtrl,0);
        BoldUnderline(g,"Alt",xAlt,0);

        if(iNumValid < iNumLines){
            for (int i = 0; i < iInserIndex; i++)
            {
                DisplayKeyInfo(g,i,i);
            }
        }else{
            for (int i = 0; i < iInserIndex; i++)
            {
                DisplayKeyInfo(g,i,(iInserIndex+1)%iNumLines);
            }
        }
    }


    protected override void OnKeyDown(KeyEventArgs e)
    {
        akeyevt[iInserIndex].evtType = EventType.KeyDown;
        akeyevt[iInserIndex].evtargs = e;
        OnKey();
    }
    protected override void OnKeyUp(KeyEventArgs e)
    {
        akeyevt[iInserIndex].evtType = EventType.KeyUp;
        akeyevt[iInserIndex].evtargs = e;
        OnKey();
    }
    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        akeyevt[iInserIndex].evtType = EventType.KeyPress;
        akeyevt[iInserIndex].evtargs = e;
        OnKey();
    }

    void OnKey(){
        if(iNumValid < iNumLines){
            var g = CreateGraphics();
            DisplayKeyInfo(g,iInserIndex,iInserIndex);
            g.Dispose();
        }else{
            ScrollLines();
        }
        iInserIndex = (iInserIndex + 1) % iNumLines;
        iNumValid = Math.Min(iNumValid+1,iNumLines);
    }   
    void BoldUnderline(Graphics g,string str,int x,int y){
        var b = new SolidBrush(ForeColor);
        g.DrawString(str,Font,b,x,y);
        g.DrawString(str,Font,b,x+1,y);
        
        var sizef = g.MeasureString(str,Font);
        g.DrawLine(new Pen(ForeColor),x,y+sizef.Height,x+sizef.Width,y+sizef.Height);
    }
    void DisplayKeyInfo(Graphics g,int y,int i){
        var b = new  SolidBrush(ForeColor);
        y = (1 + y)*Font.Height;
        // eventType
        g.DrawString(akeyevt[i].evtType.ToString(),Font,b,xEvent,y);

        if(akeyevt[i].evtType == EventType.KeyPress){
            var kpea = (KeyPressEventArgs) akeyevt[i].evtargs;
            g.DrawString(kpea.KeyChar.ToString(),Font,b,xChar,y);
        }else{
            var kea = (KeyEventArgs) akeyevt[i].evtargs;
            g.DrawString(kea.KeyCode.ToString(),Font,b,xCode,y);
            g.DrawString(kea.Modifiers.ToString(),Font,b,xMods,y);
            g.DrawString(kea.KeyData.ToString(),Font,b,xData,y);
            g.DrawString(kea.Shift.ToString(),Font,b,xShift,y);
            g.DrawString(kea.Control.ToString(),Font,b,xCtrl,y);
            g.DrawString(kea.Alt.ToString(),Font,b,xAlt,y);
        }
    }
    
    protected virtual void ScrollLines(){
        Rectangle rect = new Rectangle(0,Font.Height,ClientSize.Width,ClientSize.Height-Font.Height);
        Invalidate(rect);
    }
}